package com.mojian.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mojian.common.Result;
import com.mojian.config.AlipayConfig;
import com.mojian.entity.PayOrder;
import com.mojian.mapper.PayOrderMapper;
import com.mojian.model.vo.PayOrderVO;
import com.mojian.service.PaymentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

/**
 * 支付服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PaymentServiceImpl implements PaymentService {

    private final AlipayClient alipayClient;
    private final AlipayConfig alipayConfig;
    private final PayOrderMapper payOrderMapper;
    private final JdbcTemplate jdbcTemplate;

    /**
     * 生成订单号
     * 格式：年月日时分秒 + 4位随机数
     */
    private String generateOrderNo() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        String timeStr = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        
        // 生成4位随机数
        Random random = new Random();
        int randomNum = random.nextInt(10000);
        String randomStr = String.format("%04d", randomNum);
        
        return timeStr + randomStr;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<PayOrderVO> createAlipayOrder(PayOrderVO orderVO) {
        try {
            log.info("====== 开始创建支付订单 ======");
            // 生成订单号
            String orderNo = generateOrderNo();
            log.info("订单号: {}", orderNo);
            log.info("支付方式: {}", orderVO.getPaymentMethod());
            log.info("金额: {}", orderVO.getAmount());
            log.info("文章ID: {}", orderVO.getArticleId());
            
            orderVO.setOrderNo(orderNo);
            orderVO.setStatus("PENDING");

            // 保存订单记录
            PayOrder payOrder = PayOrder.builder()
                    .orderNo(orderNo)
                    .userId(1L) // 这里应该从当前登录用户获取ID
                    .articleId(orderVO.getArticleId())
                    .paymentMethod(orderVO.getPaymentMethod())
                    .amount(orderVO.getAmount())
                    .status("PENDING")
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            payOrderMapper.insert(payOrder);
            log.info("订单已保存到数据库");
            
            log.info("开始处理支付环节");
            log.info("支付宝配置信息: appId={}, gatewayUrl={}", alipayConfig.getAppId(), alipayConfig.getGatewayUrl());
            
            // 调用支付宝接口
            try {
                // 沙箱环境下使用预创建交易接口
                AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
                // 设置回调地址
                request.setNotifyUrl(alipayConfig.getNotifyUrl());
                
                // 构建业务请求参数
                JSONObject bizContent = new JSONObject();
                bizContent.put("out_trade_no", orderNo);
                bizContent.put("total_amount", orderVO.getAmount().toString());
                bizContent.put("subject", "文章付费阅读-" + orderVO.getArticleId());
                bizContent.put("body", "支付完成后可查看完整文章内容");
                // 设置超时时间
                bizContent.put("timeout_express", "15m");
                
                request.setBizContent(bizContent.toString());
                log.info("支付宝接口请求参数: {}", bizContent.toString());

                // 由于网络原因可能导致超时，这里设置较短的超时时间
                log.info("开始调用支付宝接口...");
                long startTime = System.currentTimeMillis();
                
                // 调用支付宝接口获取二维码链接
                AlipayTradePrecreateResponse response = alipayClient.execute(request);
                
                long endTime = System.currentTimeMillis();
                log.info("支付宝接口调用耗时: {}ms", (endTime - startTime));
                log.info("支付宝接口响应: success={}, code={}, msg={}", 
                          response.isSuccess(), response.getCode(), response.getMsg());
                
                if (response.isSuccess()) {
                    // 成功获取二维码
                    String qrCode = response.getQrCode();
                    log.info("支付宝返回二维码内容: {}", qrCode);
                    
                    // 生成二维码图片URL
                    String qrCodeUrl = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=" + qrCode;
                    log.info("生成的二维码图片URL: {}", qrCodeUrl);
                    orderVO.setQrCodeUrl(qrCodeUrl);
                    
                    log.info("最终生成二维码URL: {}", qrCodeUrl);
                    return Result.success(orderVO);
                } else {
                    log.error("创建支付宝订单失败: {}", response.getSubMsg());
                    
                    // 如果支付宝接口调用失败，返回临时二维码，避免前端出错
                    log.info("使用临时二维码作为回退方案");
                    String qrCodeUrl = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=order:" + orderNo;
                    orderVO.setQrCodeUrl(qrCodeUrl);
                    
                    return Result.success(orderVO).putExtra("warning", "支付宝接口调用失败，使用临时二维码");
                }
            } catch (Exception e) {
                log.error("调用支付宝接口异常", e);
                
                // 如果发生异常，返回临时二维码，避免前端出错
                log.info("使用临时二维码作为回退方案");
                String qrCodeUrl = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=order:" + orderNo;
                orderVO.setQrCodeUrl(qrCodeUrl);
                
                String errorMsg = e.getMessage();
                if (e instanceof java.net.SocketTimeoutException || 
                    (e.getCause() != null && e.getCause() instanceof java.net.SocketTimeoutException)) {
                    errorMsg = "支付宝接口请求超时，请稍后再试";
                    log.error("支付宝接口请求超时: {}", e.getMessage());
                }
                
                return Result.success(orderVO).putExtra("warning", errorMsg);
            }
            
        } catch (Exception e) {
            log.error("创建支付宝订单失败", e);
            return Result.error("创建支付订单失败：" + e.getMessage());
        }
    }

    @Override
    public Result<PayOrderVO> checkOrderStatus(String orderNo) {
        if (!StringUtils.hasText(orderNo)) {
            return Result.error("订单号不能为空");
        }

        log.info("开始查询订单状态: {}", orderNo);

        try {
            // 查询本地订单状态
            PayOrder payOrder = payOrderMapper.selectOne(
                    new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, orderNo)
            );

            if (payOrder == null) {
                log.error("订单不存在: {}", orderNo);
                return Result.error("订单不存在");
            }
            
            log.info("本地订单信息: orderNo={}, status={}, amount={}, articleId={}, userId={}", 
                    payOrder.getOrderNo(), payOrder.getStatus(), payOrder.getAmount(), 
                    payOrder.getArticleId(), payOrder.getUserId());
            
            // 如果本地订单已成功，直接返回
            if ("SUCCESS".equals(payOrder.getStatus())) {
                log.info("订单已支付成功: {}", orderNo);
                PayOrderVO orderVO = convertToVO(payOrder);
                return Result.success(orderVO);
            }

            // 查询支付宝订单状态
            if ("alipay".equals(payOrder.getPaymentMethod())) {
                try {
                    log.info("调用支付宝查询接口检查订单状态: {}", orderNo);
                    
                    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
                    JSONObject bizContent = new JSONObject();
                    bizContent.put("out_trade_no", orderNo);
                    
                    request.setBizContent(bizContent.toString());
                    log.info("支付宝查询接口请求参数: {}", bizContent.toString());
                    
                    // 记录查询开始时间
                    long startTime = System.currentTimeMillis();
                    
                    // 调用支付宝接口查询订单状态
                    AlipayTradeQueryResponse response = alipayClient.execute(request);
                    
                    long endTime = System.currentTimeMillis();
                    log.info("支付宝查询接口调用耗时: {}ms", (endTime - startTime));
                    log.info("支付宝查询响应: success={}, code={}, msg={}, tradeStatus={}", 
                            response.isSuccess(), response.getCode(), response.getMsg(), response.getTradeStatus());
                    
                    if (response.isSuccess()) {
                        // 根据支付宝返回状态更新订单
                        String tradeStatus = response.getTradeStatus();
                        log.info("订单[{}]支付宝返回交易状态: {}", orderNo, tradeStatus);
                        
                        if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                            log.info("订单[{}]已支付成功，更新本地订单状态", orderNo);
                            
                            // 更新订单状态为支付成功
                            payOrder.setStatus("SUCCESS");
                            payOrder.setTradeNo(response.getTradeNo());
                            payOrder.setPayTime(LocalDateTime.now());
                            payOrder.setUpdateTime(LocalDateTime.now());
                            int rows = payOrderMapper.updateById(payOrder);
                            
                            log.info("订单[{}]状态已更新为SUCCESS, 影响行数: {}", orderNo, rows);
                            
                            // 手动刷新缓存，确保后续查询能获取到最新状态
                            payOrder = payOrderMapper.selectById(payOrder.getId());
                            log.info("刷新后订单状态: {}", payOrder.getStatus());

                            // 更新文章的readType为1（免费），使支付后可以阅读
                            try {
                                String articleIdStr = payOrder.getArticleId();
                                if (articleIdStr != null && !articleIdStr.isEmpty()) {
                                    Long articleId = Long.parseLong(articleIdStr);
                                    log.info("更新文章[{}]的阅读类型为免费", articleId);
                                    // 使用JdbcTemplate更新文章的readType
                                    jdbcTemplate.update(
                                        "UPDATE sys_article SET read_type = 1 WHERE id = ? AND (read_type = 2 OR read_type = 3)",
                                        articleId
                                    );
                                    log.info("文章[{}]已更新为免费阅读状态", articleId);
                                }
                            } catch (Exception e) {
                                log.error("更新文章阅读类型失败", e);
                            }
                        } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                            log.info("订单[{}]等待买家付款中", orderNo);
                            payOrder.setStatus("PENDING");
                            payOrder.setUpdateTime(LocalDateTime.now());
                            payOrderMapper.updateById(payOrder);
                        } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                            log.info("订单[{}]已关闭", orderNo);
                            payOrder.setStatus("CLOSED");
                            payOrder.setUpdateTime(LocalDateTime.now());
                            payOrderMapper.updateById(payOrder);
                        }
                    } else {
                        // 查询失败，记录错误信息
                        log.error("查询支付宝订单状态失败: code={}, msg={}, subCode={}, subMsg={}", 
                                response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
                        
                        // 如果返回"交易不存在"，可能是订单还未生成或已过期
                        if ("ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())) {
                            log.info("订单[{}]在支付宝中不存在，可能未创建或已过期", orderNo);
                        }
                    }
                } catch (AlipayApiException e) {
                    log.error("查询支付宝订单状态异常", e);
                }
            } else {
                log.info("非支付宝支付方式，无需查询支付宝状态: {}", payOrder.getPaymentMethod());
            }

            // 返回最新订单信息
            PayOrder updatedOrder = payOrderMapper.selectOne(
                    new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, orderNo)
            );
            
            log.info("返回最新订单状态: orderNo={}, status={}", updatedOrder.getOrderNo(), updatedOrder.getStatus());
            
            PayOrderVO orderVO = convertToVO(updatedOrder);
            return Result.success(orderVO);
        } catch (Exception e) {
            log.error("查询订单状态异常", e);
            return Result.error("查询订单状态失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String handleAlipayNotify(Map<String, String> params) {
        log.info("接收到支付宝异步通知：{}", params);
        
        try {
            // 验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(
                    params,
                    alipayConfig.getAlipayPublicKey(),
                    alipayConfig.getCharset(),
                    alipayConfig.getSignType()
            );
            
            if (!signVerified) {
                log.error("支付宝异步通知验签失败");
                return "failure";
            }
            
            // 验证关键参数
            String orderNo = params.get("out_trade_no");
            String tradeStatus = params.get("trade_status");
            String tradeNo = params.get("trade_no");
            String totalAmount = params.get("total_amount");
            
            if (!StringUtils.hasText(orderNo) || !StringUtils.hasText(tradeStatus)) {
                return "failure";
            }
            
            // 查询本地订单
            PayOrder payOrder = payOrderMapper.selectOne(
                    new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getOrderNo, orderNo)
            );
            
            if (payOrder == null) {
                log.error("订单不存在：{}", orderNo);
                return "failure";
            }
            
            // 验证金额是否一致
            if (new BigDecimal(totalAmount).compareTo(payOrder.getAmount()) != 0) {
                log.error("订单金额不匹配：{}", orderNo);
                return "failure";
            }
            
            // 处理订单状态
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                if (!"SUCCESS".equals(payOrder.getStatus())) {
                    payOrder.setStatus("SUCCESS");
                    payOrder.setTradeNo(tradeNo);
                    payOrder.setPayTime(LocalDateTime.now());
                    payOrder.setUpdateTime(LocalDateTime.now());
                    payOrderMapper.updateById(payOrder);
                    
                    // 更新文章的readType为1（免费），使支付后可以阅读
                    try {
                        String articleIdStr = payOrder.getArticleId();
                        if (articleIdStr != null && !articleIdStr.isEmpty()) {
                            Long articleId = Long.parseLong(articleIdStr);
                            log.info("更新文章[{}]的阅读类型为免费", articleId);
                            // 使用JdbcTemplate更新文章的readType
                            jdbcTemplate.update(
                                "UPDATE sys_article SET read_type = 1 WHERE id = ? AND (read_type = 2 OR read_type = 3)",
                                articleId
                            );
                            log.info("文章[{}]已更新为免费阅读状态", articleId);
                        }
                    } catch (Exception e) {
                        log.error("更新文章阅读类型失败", e);
                    }
                }
            }
            
            return "success";
        } catch (AlipayApiException e) {
            log.error("处理支付宝异步通知失败", e);
            return "failure";
        }
    }
    
    /**
     * 将实体转换为VO
     */
    private PayOrderVO convertToVO(PayOrder payOrder) {
        return PayOrderVO.builder()
                .orderNo(payOrder.getOrderNo())
                .articleId(payOrder.getArticleId())
                .paymentMethod(payOrder.getPaymentMethod())
                .amount(payOrder.getAmount())
                .status(payOrder.getStatus())
                .build();
    }

    /**
     * 检查用户是否已支付指定文章
     * @param userId 用户ID
     * @param articleId 文章ID
     * @return 是否已支付
     */
    @Override
    public boolean checkArticlePaid(Long userId, Long articleId) {
        if (userId == null || articleId == null) {
            return false;
        }
        
        log.info("检查用户[{}]是否已支付文章[{}]", userId, articleId);
        
        try {
            // 查询该用户是否已支付此文章
            PayOrder payOrder = payOrderMapper.selectOne(
                new LambdaQueryWrapper<PayOrder>()
                    .eq(PayOrder::getUserId, userId)
                    .eq(PayOrder::getArticleId, articleId)
                    .eq(PayOrder::getStatus, "SUCCESS")
            );
            
            boolean isPaid = payOrder != null;
            log.info("用户[{}]支付文章[{}]状态: {}", userId, articleId, isPaid ? "已支付" : "未支付");
            
            return isPaid;
        } catch (Exception e) {
            log.error("检查文章支付状态异常", e);
            return false;
        }
    }
} 